var Map = require('../DAO/schemaMap.js').Map;

var tilesFuncs = require('../DAO/schemaTile.js');

var gv = require('../globalVars.js').gv;
var converter = require('./converter.js');

function events(socket){

    socket.on('tile_update', updateTile);

}

function initMap(){
    var map = new Map();
        map.setGridWH(gv.gridWidth, gv.gridWidth);
        map.setDefaultTileWH(gv.tileWidth, gv.tileHeight);
        map.playerAreaBase = gv.playerArea;
        map.playerRangeBase = gv.playerRange;

    initTiles(map);

    map.save(function(err){
        if (err){
            console.log('Error saving map : ' + err);
        } else {
            //TODO send new map à l'user pour qu'il reload la page (grid = null bug client side)
            console.log('--- NEW MAP INIT ---');
        }
    });
}

function initTiles(map){
    var tilesMap = [];

    for (var row = 0, i = 1; row < map.grid.width; row++) {
        tilesMap[row] = [];

        for (var col = 0; col < map.grid.height; col++, i++) {
            //obj Tile = id, row, col
            tilesMap[row][col] = tilesFuncs.newTile(i,row,col);
        }
    }

    initHealthLevel(tilesMap, map.grid);
    map.setTiles(tilesMap);
}

function initHealthLevel(tilesMap, grid) {
//    Bandes de 5 tiles avec 4 niveaux de fertilité / 25% --> 25-50,50-75...
    for (var row = 0; row < grid.width; row++) {
        for (var col = 0; col < grid.height; col++) {
            if(tilesMap[row][col].fertility != null) continue;

            var rndFertility = rdmInterval(1,4);
            var rndTileOnBand = null;

            for(var i = 0; i < 5; i++) {
                //Si on est sur la map et que la tile n'a pas déjà un niveau de fertilité
                if(row + i < grid.width){
                    switch(rndFertility){
                        case 1: rndTileOnBand = rdmInterval(5,25); break;
                        case 2: rndTileOnBand = rdmInterval(26,50); break;
                        case 3: rndTileOnBand = rdmInterval(51,75); break;
                        case 4: rndTileOnBand = rdmInterval(76,100); break;
                    }

                    tilesMap[row + i][col].fertility = rndTileOnBand;

                    switch(rndFertility){
                        case 1: tilesMap[row + i][col].fertilityCap = 25; break;
                        case 2: tilesMap[row + i][col].fertilityCap = 50; break;
                        case 3: tilesMap[row + i][col].fertilityCap = 75; break;
                        case 4: tilesMap[row + i][col].fertilityCap = 100; break;
                    }
                }
            }
        }
    }
}

// Math RMD Tool
function rdmInterval(from,to) { return Math.floor(Math.random() * (to - from + 1) + from); }

// Update canPass, humidity, fertility
function updateTile(tile, id_map){

    var tile_doc = converter.tileToDoc(tile);

    Map.findById(id_map, function(err, map){
        if(!err){
            map.tiles[tile_doc.position.row][tile_doc.position.col].canPass = tile_doc.canPass;
            map.tiles[tile_doc.position.row][tile_doc.position.col].humidity = tile_doc.humidity;
            map.tiles[tile_doc.position.row][tile_doc.position.col].fertility = tile_doc.fertility;
			
			var t_update = map.tiles[tile_doc.position.row][tile_doc.position.col];
            t_update.canPass = tile_doc.canPass;
            t_update.humidity = tile_doc.humidity;
            t_update.fertility = tile_doc.fertility;
            t_update.healthLevel = tile_doc.healthLevel;
			
            map.markModified('tiles');
            map.save(function(err){
                if (!err) console.log('Tile saved');
                else console.log('Error: ' + err);
            })
        }
    })
}

//
// --- NEW PLAYER INC FUNCS ---
//

//Quand un nouveau joueur rejoint la partie
//placement de ce dernier, ou expension de la map si la place manque
function newPlayerOnMap(map, hero) {
    for (var row = 0; row < map.grid.width - 1; row++) {
        for (var col = 0; col < map.grid.height - 1; col++) {
            if(map.tiles[row][col].heroId != null) continue;

            var rslt = _tryNewPlayerAtRowCol(map, row, col, hero);

            if(rslt == true) {
                _setupNewPlayerAtRowCol(map,hero,row,col);
                return;
            }
        }
    }

    //Si on a pas pu placer le joueur dans la map existante, on l'agrandit
    var newGridRows = map.grid.width + map.playerRangeBase + (map.playerAreaBase * 2 + 1);
    var newGridCols = map.grid.height + map.playerRangeBase + (map.playerAreaBase * 2 + 1);

    _setNewTiles(map,newGridRows,newGridCols,hero);

}

//test si la tile @ row & col est éligible pour une zone de départ
//en respectant les valeurs playerAreaBase & playerRangeBase
function _tryNewPlayerAtRowCol(map, row, col, hero) {
    if(     row + map.playerAreaBase + map.playerRangeBase >= map.grid.width
        ||  row - map.playerAreaBase - map.playerRangeBase < 0
        ||  col + map.playerAreaBase + map.playerRangeBase >= map.grid.height
        ||  col - map.playerAreaBase - map.playerRangeBase < 0)
        return false;


    for(var tryRow = row - map.playerAreaBase - map.playerRangeBase;
        tryRow <= row + map.playerAreaBase + map.playerRangeBase; tryRow++) {
        for(var tryCol = col - map.playerAreaBase - map.playerRangeBase;
            tryCol <= col + map.playerAreaBase + map.playerRangeBase; tryCol++) {
            if(map.tiles[tryRow][tryCol].heroId != null)
                return false;
        }
    }

//    console.log('--- _tryNewPlayerAtRowCol() : returning true for '+row+','+col+' ---');
    hero.pos.row = row;
    hero.pos.col = col;
    hero.save();
    return true;
}


function _setupNewPlayerAtRowCol(map,hero,row,col) {
    var passed = false;
    for (var pRow = row - map.playerAreaBase; pRow <= row + map.playerAreaBase; pRow++) {
        for (var pCol = col - map.playerAreaBase; pCol <= col + map.playerAreaBase; pCol++) {
//            console.log('trying to put hero '+hero.name+' on tile '+pRow+','+pCol+' (id : '+map.tiles[pRow][pCol].id+').');
                map.tiles[pRow][pCol].heroId = hero._id;
                hero.tiles.push(map.tiles[pRow][pCol]);
        }
    }

    map.markModified('tiles');
    map.save(function(err){
        if (err)console.log('Error player start zone (map): ' + err.message);
    });

    hero.markModified('tiles');
    hero.save(function(err) {
        if(err) console.log('Error player start zone (tile) : '+err.message);
    })

    console.log('--- _setupNewPlayerAtRowCol() : hero '+hero.name+' zone set from tile '+row+','+col+' ---');
}

function _setNewTiles(map, newMaxWidth, newMaxHeight, hero) {
    //new tiles sur la largeur
    for(var row = map.grid.width; row < newMaxWidth; row++) {
        map.tiles[row] = [];
        for(var col = 0; col < map.grid.height; col++) {
            map.tiles[row][col] = tilesFuncs.newTile(-42,row,col);
        }
    }

    //new tiles sur la hauteur
    for(row = 0; row < map.grid.width; row++) {
        for(col = map.grid.height; col < newMaxHeight; col++) {
            map.tiles[row][col] = tilesFuncs.newTile(-42,row,col);
        }
    }

    //new tiles sur la diagonale
    for (row = map.grid.width; row < newMaxWidth; row++) {
        for(col = map.grid.height; col < newMaxHeight; col++) {
            map.tiles[row][col] = tilesFuncs.newTile(-42,row,col);
        }
    }

    //reassign all tile's IDs (used client-side)
    for (var i = 1, row = 0; row < newMaxWidth; row++) {
        for(col = 0; col < newMaxHeight; col++, i++) {
            map.tiles[row][col].id = i;
        }
    }



    map.markModified('tiles');
    map.setGridWH(newMaxWidth, newMaxHeight);
    initHealthLevel(map.tiles,map.grid);
    map.save(function(err) {
        if(err) console.log('--- err expding map: '+err);
        else  {
            console.log('--- EXPDING SUCCESS for new player');
            newPlayerOnMap(map, hero);
        }
    });

    console.log('--- _setNewTiles() : new maxs WH = '+newMaxWidth+';'+newMaxHeight+' ---');
}

exports.events = events;
exports.initMap = initMap;
exports.newPlayerOnMap = newPlayerOnMap;
